/*
* 通过类似于typeof age===”number“的判断语句，来改变Typescript的执行路径
* 在给定的执行路径中，我们可以缩小比声明时更小的类型，这个过程称之为缩小
* typeof age===”number“的判断语句可以称之为类型保护
*  常见的类型保护有：typeof、平等缩小(=== !==)、instanceof、 in等
* */


type messageType = string | number | boolean

// typeof进行类型缩小
function getMessage(message: messageType): messageType {
    if (typeof message === "number") {
        return message.toFixed(3)
    } else if (typeof message === "string") {
        return message.length
    } else if (typeof message === "boolean") {
        return message
    }
}

const res1: messageType = getMessage(10)
console.log(res1)
const res2: messageType = getMessage("typescript||JavaScript")
console.log(res2)
const res3: messageType = getMessage(false)
console.log(res3)


// 平等缩小
type DirectionType = "left" | "top" | "right" | "bottom"

function switchDirection(position: DirectionType): DirectionType {
    switch (position) {
        case "left":
            return "left"
        case "right":
            return "right"
        case "bottom":
            return "bottom"
        case "top":
            return "top"
    }

}

const res4: DirectionType = switchDirection("left")
console.log(res4)


// 使用instanceof进行类型缩小
type DateType = string | Date

function getDate(result: DateType): DateType {
    if (result instanceof Date) {
        return result
    } else {
        return result + 10
    }
}

console.log(getDate(new Date()))

/*
in操作符进行类型缩小
    JavaScript有一个运算符，用于确定对象是否具有带名称的属性：in运算符
    如果指定的属性在指定的对象或原型链中，则in运算符返回true
*/
interface InterfaceSwim {
    Swim: () => void
}
interface InterfaceRun {
    Run: () => void
}

function move(animal: InterfaceRun | InterfaceSwim) {
    if ("Swim" in animal) {
        animal.Swim()
    } else if ("Run" in animal) {
        animal.Run()
    }
}

const fish: InterfaceSwim = {
    Swim(): void {
        console.log("游泳")
    }
}
const dog: InterfaceRun = {
    Run(): void {
        console.log("跑步")
    }
}
move(fish)
move(dog)
